﻿#include "bspool.h"
#include "beanstalk.h"

#define MAX_COUNT 16

int bsp_init(bspool_t* bspool) {
	bspool->capacity = MAX_COUNT;
	bspool->count = 0;
	bspool->alloc = 0;
	bspool->handles = malloc(sizeof(int) * bspool->capacity);

	if (bspool->handles)
		return BS_STATUS_OK;
	else
		return BS_STATUS_FAIL;
}

int bsp_deinit(bspool_t* bspool) {
	int i = 0;
	for (;i < bspool->count; ++i) {
		bs_close(bspool->handles[i]);
	}
	free(bspool->handles);
	bspool->handles = NULL;
	bspool->count = 0;
	bspool->capacity = 0;

	return BS_STATUS_OK;
}

bspool_t* bsp_new_pool() {
	bspool_t* pool = malloc(sizeof(bspool_t));
	if (!pool)
		return NULL;
	if (bsp_init(pool) != BS_STATUS_OK) {
		free(pool);
		return NULL;
	}
	return pool;
}

void bsp_free_pool(bspool_t* pool) {
	if (pool) {
		bsp_deinit(pool);
		free(pool);
	}
}

int bsp_connect(bspool_t* bspool,const char *host, int port) {
	return bsp_connect_with_timeout(bspool,host,port,-1);
}

int bsp_connect_with_timeout(bspool_t* bspool, const char *host, int port, float secs) {
	if (bspool->alloc < bspool->capacity || bspool->count == 0) {
		//创建新的连接
		int socket;

		if(secs<0)
			socket = bs_connect(host, port);
		else
			socket = bs_connect_with_timeout(host, port, secs);

		if (socket > 0) {
			++bspool->alloc;
		}
		return socket;
	} else {
		int r = rand() % bspool->count;
		int socket = bspool->handles[r];

		//移除
		memmove(bspool->handles + r, bspool->handles + r + 1, (bspool->count - r) * sizeof(int));
		--bspool->count;

		if (bs_ping(socket) == BS_STATUS_OK) {
			//ping成功，返回socket
			return socket;
		} else {
			//ping失败，创建新的
			bs_close(socket);
			if (secs < 0)
				socket = bs_connect(host, port);
			else
				socket = bs_connect_with_timeout(host, port, secs);

			if (socket < 0) {
				//重新创建失败
				--bspool->alloc;
			}
			return socket;
		}
	}
}

int bsp_close(bspool_t* bspool, int fd) {
	if (fd < 0)
		return BS_STATUS_FAIL;

	if (bspool->count < bspool->capacity) {
		//放入到pool中
		bspool->handles[bspool->count] = fd;
		++bspool->count;
	} else {
		//pool已满，直接关闭
		bs_close(fd);
	}
	return BS_STATUS_OK;
}

